﻿using Cysharp.Threading.Tasks;
using HarmonyLib;
using LBoL.Base;
using LBoL.ConfigData;
using LBoL.Core;
using LBoL.Core.Cards;
using MBP.ModBase;
using Newtonsoft.Json;
using SimpleJSON;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using UnityEngine;
using YamlDotNet.RepresentationModel;
using YamlDotNet.Serialization;

namespace ModBasePlugin
{
    public class ModCardManager : IManager
    {
        public static BepInEx.Logging.ManualLogSource logger;

        public const string DatasPath = "\\Datas\\Cards";
        public const string LocalizationPath = "\\Localization";
        public const string ScriptsPath = "\\Scripts\\Cards";
        public const string ImgsPath = "\\Imgs\\Cards";

        public List<ModCard> ExtraModCards { get; set; } = new List<ModCard>();
        public Dictionary<string, Dictionary<string, object>> ModCardLocalization { get; set; } = new Dictionary<string, Dictionary<string, object>>();
        public Dictionary<string, Texture> CardImgDic { get; set; } = new Dictionary<string, Texture>();

        public void Init()
        {

            foreach (var mod in PluginManager.ModInfos)
            {
                var dir = new DirectoryInfo(mod.mod_path+DatasPath);
                //  读取json
                var cardJsons = dir.GetFiles("*.json");
                if (cardJsons.Length < 0)
                {
                    continue;
                }

                foreach (var file in cardJsons)
                {
                    var jsonText = file.OpenText().ReadToEnd();
                    JSONArray modCards = JSON.Parse(jsonText).AsArray;
                    //var modCards = JsonConvert.DeserializeObject<List<ModCard>>(jsonText);
                    foreach(var j in modCards.Children)
                    {
                        ModCard mc = new ModCard(j);
                        mc.modid = mod.id;
                        ExtraModCards.Add(mc);                       
                    }
                }

                var lPath = LocalizationPath;
                // 获取当前语言
                switch (Localization.CurrentLocale)
                {
                    default:
                        lPath = lPath + "\\ZhHans";
                        break;
                }
                lPath = lPath + "\\Cards";

                // 读取yaml
                var dirL = new DirectoryInfo(mod.mod_path + lPath);
                var cardYamls = dirL.GetFiles("*.yaml");
                var t = Traverse.Create(typeof(Localization));
                foreach (var f in cardYamls)
                {
                    var yamlText = f.OpenText();
                    var yaml = new YamlStream();
                    yaml.Load(yamlText);
                    var mapping = (YamlMappingNode)yaml.Documents[0].RootNode;
                    var dic = new Dictionary<string, Dictionary<string, object>>();
                    foreach (var entry in mapping.Children)
                    {
                        var vDic = new Dictionary<string, object>();
                        foreach (var vEntry in (YamlMappingNode)entry.Value)
                        {
                            vDic.Add((string)vEntry.Key, (string)vEntry.Value);
                        }
                        dic.Add((string)entry.Key, vDic);
                    }

                    ModCardLocalization = ModCardLocalization.Concat(dic).ToDictionary(k =>  k.Key , v => v.Value);
                }
                LoadImgFile(mod.mod_path + ImgsPath);
            }
        }

        public CardConfig[] GetCardConfigs(int CurrCardsLen)
        {
            var configs = new List<CardConfig>();
            for(int i = 0; i < ExtraModCards.Count; i++)
            {
                var mc = ExtraModCards[i];

                var Perform = new string[1][] {new string[] { "" } };
                var GunName = "";
                var GunNameBurst = "";

                var ManaCost = IntToMana(mc.card_datas_dic["Cost"],out bool isX);
                var PlusManaCost = IntToMana(mc.card_plus_datas_dic["Cost"], out _);

                var MoneyCost = mc.GetDataValue("MoneyCost", false);

                var Damage = mc.GetDataValue("Damage", false);
                var PlusDamage = mc.GetDataValue("Damage", true);

                var Block = mc.GetDataValue("Block", false);
                var PlusBlock = mc.GetDataValue("Block", true);

                var Shield = mc.GetDataValue("Shield", false);
                var PlusShield = mc.GetDataValue("Shield", true);

                var ManaInt = mc.GetDataValue("Mana", false);
                var PlusManaInt = mc.GetDataValue("Mana", true);
                var Mana = IntToMana(ManaInt, out _);
                var PlusMana = IntToMana(PlusManaInt, out _);

                var Scry = mc.GetDataValue("Scry", false);
                var PlusScry = mc.GetDataValue("Scry", true);

                var ToolPlayableTimes = mc.GetDataValue("ToolPlayableTimes", false);

                var Keyword = mc.GetKeyword(false);
                var PlusKeyword = mc.GetKeyword(true);

                var RelativeEffects = new List<string>() {  };
                var PlusRelativeEffects = new List<string>() {  };

                var SubIllustrator = new List<string>();
                var SubUnfinished = new List<bool>();

                //  获取构造函数
                var Constructor = typeof(CardConfig).GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance).FirstOrDefault();

                //  Value1作为是否是MOD卡的标志位,值为22
                List<object> pars = new List<object>() {                     
                    i+CurrCardsLen,
                    mc.id,
                    0,
                    false,
                    false,
                    Perform,
                    GunName,
                    GunNameBurst,
                    false,
                    mc.is_pooled,
                    mc.is_upgradable,
                    mc.rarity,
                    mc.card_type,
                    mc.target_type,
                    mc.color,
                    isX,
                    ManaCost,
                    PlusManaCost,
                    MoneyCost,
                    Damage,
                    PlusDamage,
                    Block,
                    PlusBlock,
                    Shield,
                    PlusShield,
                    22,
                    0,
                    0,
                    0,
                    Mana,
                    PlusMana,
                    Scry,
                    PlusScry,
                    ToolPlayableTimes,
                    Keyword,
                    PlusKeyword,
                    false,
                    Keyword,
                    PlusKeyword,
                    RelativeEffects,
                    PlusRelativeEffects,
                    mc.relative_cards,
                    mc.relative_cards,
                    mc.ownner,
                    true,
                    "",
                    SubIllustrator,
                    SubUnfinished
                };

                var cc = Constructor.Invoke(pars.ToArray()) as CardConfig;
                
                configs.Add(cc);
            }
            return configs.ToArray();
        }

        public List<Type> GetModCardTypes()
        {
            List<Type> AllModCardTypes = new List<Type>();

            foreach (var mod in PluginManager.ModInfos)
            {
                var modAssembly = Assembly.LoadFrom(mod.mod_path + ModCardManager.ScriptsPath + "\\" + "LBoL.Cards" + ".dll");
                var cardTypes = modAssembly.GetTypes();
                foreach(var ct in cardTypes)
                {
                    if (!CompilerGen(ct))
                    {
                        AllModCardTypes.Add(ct);
                    }
                }
            }
            return AllModCardTypes;
        }

        private ManaGroup IntToMana(int cost, out bool isXCost)
        {
            var costArr = new int[9];

            int c = cost;

            for (int i = 0; i < 9; i++)
            {
                costArr[i] = c % 10;
                c /= 10;
            }

            isXCost = costArr[8] > 0;

            return new ManaGroup()
            {
                Any = costArr[7],
                White = costArr[6],
                Blue = costArr[5],
                Black = costArr[4],
                Red = costArr[3],
                Green = costArr[2],
                Colorless = costArr[1],
                Philosophy = costArr[0]
            };
        }

        private bool CompilerGen(Type t)
        {
            var attr = Attribute.GetCustomAttribute(t, typeof(CompilerGeneratedAttribute));
            return attr != null;
        }


        /// <summary>
        /// 读取指定目录下所有图片文件
        /// </summary>
        private void LoadImgFile(string dirPath)
        {
            string[] exts = new string[] { "*.png","*.jpg" };
            var dir = new DirectoryInfo(dirPath);

            foreach(var ext in exts)
            {
                var files = dir.GetFiles(ext);
                foreach(var f in files)
                {
                    var fs = f.OpenRead();
                    byte[] byData = new byte[fs.Length];
                    fs.Read(byData, 0, byData.Length);
                    fs.Close();

                    var tt = new Texture2D(1024,512);
                    tt.LoadImage(byData);

                    CardImgDic.Add(Path.GetFileNameWithoutExtension(f.Name), tt);
                }
            }
            
            

        }
    }
}
